package com.example.springcloud.order.service.tcc;

import com.alibaba.fastjson.JSONObject;
import com.example.springcloud.order.dto.OrderDTO;
import com.example.springcloud.order.entity.Order;
import com.example.springcloud.order.enums.OrderStatus;
import com.example.springcloud.order.feign.AccountServiceFeign;
import com.example.springcloud.order.feign.StorageServiceFeign;
import com.example.springcloud.order.mapper.OrderMapper;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;

/**
 * 订单 TCC 服务实现
 */
@Slf4j
@Service
public class OrderTCCServiceImpl implements OrderTCCService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private StorageServiceFeign storageServiceFeign;

    @Autowired
    private AccountServiceFeign accountServiceFeign;

    /**
     * Try 阶段：创建订单并冻结资源
     */
    @Override
    public Order tryCreate(OrderDTO orderDTO) {
        log.info("========TCC Try 阶段：创建订单========");
        log.info("全局事务 XID: {}", RootContext.getXID());

        // 1. 创建订单，状态为创建中
        Order order = new Order();
        order.setUserId(orderDTO.getUserId());
        order.setProductId(orderDTO.getProductId());
        order.setCount(orderDTO.getCount());
        order.setMoney(orderDTO.getMoney());
        order.setStatus(OrderStatus.CREATING.getCode());
        order.setCreateTime(LocalDateTime.now());
        order.setUpdateTime(LocalDateTime.now());

        orderMapper.insert(order);
        log.info("订单创建成功（创建中状态），订单ID: {}", order.getId());

        // 2. 冻结库存（Try）
        log.info("调用库存服务 Try 冻结库存");
        storageServiceFeign.deductTccTry(orderDTO.getProductId(), orderDTO.getCount());
        log.info("库存冻结成功");

        // 3. 冻结账户余额（Try）
        log.info("调用账户服务 Try 冻结余额");
        accountServiceFeign.deductTccTry(orderDTO.getUserId(), orderDTO.getMoney());
        log.info("余额冻结成功");

        log.info("========TCC Try 阶段完成========");
        return order;
    }

    /**
     * Confirm 阶段：确认订单，扣减资源
     */
    @Override
    public boolean confirm(BusinessActionContext context) {
        log.info("========TCC Confirm 阶段：确认订单========");
        log.info("全局事务 XID: {}", context.getXid());

        // 获取 Try 阶段的参数（Seata 会将参数序列化为 JSONObject）
        Object orderDTOObj = context.getActionContext("orderDTO");
        OrderDTO orderDTO;
        if (orderDTOObj instanceof JSONObject) {
            orderDTO = ((JSONObject) orderDTOObj).toJavaObject(OrderDTO.class);
        } else {
            orderDTO = (OrderDTO) orderDTOObj;
        }

        // ✅ 获取订单ID（Try 阶段返回的 Order 对象会被保存在 context 的 result 中）
        Object result = context.getActionContext("result");
        assert result != null;
        Long orderId = ((Order) result).getId();
        if (orderId != null) {
            // ✅ 更新订单状态为已完成
            Order order = new Order();
            order.setId(orderId);
            order.setStatus(OrderStatus.FINISHED.getCode());
            order.setUpdateTime(LocalDateTime.now());
            orderMapper.updateById(order);
            log.info("订单状态已更新为已完成，订单ID: {}", orderId);
        } else {
            log.warn("未找到订单ID，无法更新订单状态");
        }

        // 注意：库存和账户的 Confirm 会自动由 Seata 调用
        if (orderDTO != null) {
            log.info("订单确认完成，用户ID: {}, 商品ID: {}", orderDTO.getUserId(), orderDTO.getProductId());
        }

        log.info("========TCC Confirm 阶段完成========");
        return true;
    }

    /**
     * Cancel 阶段：取消订单，释放资源
     */
    @Override
    public boolean cancel(BusinessActionContext context) {
        log.info("========TCC Cancel 阶段：取消订单========");
        log.info("全局事务 XID: {}", context.getXid());

        // 获取 Try 阶段的参数（Seata 会将参数序列化为 JSONObject）
        Object orderDTOObj = context.getActionContext("orderDTO");
        OrderDTO orderDTO;
        if (orderDTOObj instanceof JSONObject) {
            orderDTO = ((JSONObject) orderDTOObj).toJavaObject(OrderDTO.class);
        } else {
            orderDTO = (OrderDTO) orderDTOObj;
        }

        // ✅ 获取订单ID（Try 阶段返回的 Order 对象会被保存在 context 的 result 中）
        Object result = context.getActionContext("result");
        assert result != null;
        Long orderId = ((Order) result).getId();
        if (orderId != null) {
            // ✅ 更新订单状态为已取消
            Order order = new Order();
            order.setId(orderId);
            order.setStatus(OrderStatus.CANCELLED.getCode());
            order.setUpdateTime(LocalDateTime.now());
            orderMapper.updateById(order);
            log.info("订单状态已更新为已取消，订单ID: {}", orderId);
        } else {
            log.warn("未找到订单ID，无法更新订单状态");
        }

        // 注意：库存和账户的 Cancel 会自动由 Seata 调用
        if (orderDTO != null) {
            log.info("订单取消完成，用户ID: {}, 商品ID: {}", orderDTO.getUserId(), orderDTO.getProductId());
        }

        log.info("========TCC Cancel 阶段完成========");
        return true;
    }
}

